package com.atyun;

import com.atyun.gaojin.notify.AlterNotify;
import com.atyun.gaojin.notify.consoleNotify.AlterNotifyConsoleImpl;
import com.atyun.gaojin.notify.mailQQNotify.MailQQNotify;
import com.atyun.properties.DtpProperties;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.*;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.ResolvableType;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;


/**
 * 注册bean阶段，在configurationProperties(bean初始化之前)前生效
 * ImportBeanDefinitionRegistrar：注册bean
 * EnvironmentAware：项目启动时可直接访问配置文件信息，比如yaml文件
 * 需要将yaml配置文件信息绑定到properties中
 * 需要该register类的原因：动态的为每个Executor类注册一个单独的bean，这是properties做不到的(只能做绑定，并且@bean注解只能静态的注册bean)
 * @Author: 云水瑶
 * @Date: 2025/4/26
*/
public class DtpBeanDefinitionRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware {

    private Environment environment;

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
        System.out.println("bean注册阶段：获取配置文件信息 + 转为DtpProperties对象格式，循环为每一个线程池注册bean");
        //首先，应该思考到如何拿到DtpProperties中的线程池属性集合
        DtpProperties dtpProperties = new DtpProperties();
        Binder binder = Binder.get(environment); //拿取到yaml配置文件信息
        ResolvableType resolvableType = ResolvableType.forClass(DtpProperties.class);
        Bindable<?> bindable = Bindable.of(resolvableType).withExistingValue(dtpProperties);
        binder.bind("dtp", bindable);

        //需要先注册告警通知
        String alterNotify = dtpProperties.getAlter().getAlterNotify();
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(AlterNotify.class, () -> {
            //TODO: 针对于后续接入多个告警策略，可通过工厂+策略做横向扩展，代替大量if-else
            if(alterNotify.equals("alterNotifyConsoleImpl")) {
                return new AlterNotifyConsoleImpl();
            } else if(alterNotify.equals("mailQQNotify")) {
                return new MailQQNotify();
            }
            return new AlterNotifyConsoleImpl();
        });
        registry.registerBeanDefinition(alterNotify, builder.getBeanDefinition());

        //循环注册Executor
        for(DtpProperties.DtpExecutorProperties entry : dtpProperties.getExecutor()) {

            String poolName = entry.getPoolName();
            //通过beanDefinition创建bean实例，然后属性赋值
            AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
            beanDefinition.setBeanClass(DptExecutor.class);
            beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(poolName);
            beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(entry.getCorePoolSize());
            beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(entry.getMaximumPoolSize());
            //注入引用对象，需要对象名，还有包路径
            beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(new RuntimeBeanReference(alterNotify));
            System.out.println("bean注册阶段：当前注册线程池：" + poolName + " 核心线程：" + entry.getCorePoolSize() + " 最大线程：" + entry.getMaximumPoolSize());
            registry.registerBeanDefinition(poolName, beanDefinition);
        }
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
}
